noexcept for <forward_list>. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@132553 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/deque b/include/deque index 71fa7f8..6ada42a 100644 --- a/include/deque +++ b/include/deque
@@ -948,7 +948,7 @@ #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void swap(__deque_base& __c) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value); protected: void clear() _NOEXCEPT;
diff --git a/include/forward_list b/include/forward_list index 1babc8f..2387bce 100644 --- a/include/forward_list +++ b/include/forward_list
@@ -34,7 +34,8 @@ typedef <details> iterator; typedef <details> const_iterator; - forward_list(); + forward_list() + noexcept(is_nothrow_default_constructible<allocator_type>::value); explicit forward_list(const allocator_type& a); explicit forward_list(size_type n); forward_list(size_type n, const value_type& v); @@ -45,7 +46,8 @@ forward_list(InputIterator first, InputIterator last, const allocator_type& a); forward_list(const forward_list& x); forward_list(const forward_list& x, const allocator_type& a); - forward_list(forward_list&& x); + forward_list(forward_list&& x) + noexcept(is_nothrow_move_constructible<allocator_type>::value); forward_list(forward_list&& x, const allocator_type& a); forward_list(initializer_list<value_type> il); forward_list(initializer_list<value_type> il, const allocator_type& a); @@ -53,7 +55,10 @@ ~forward_list(); forward_list& operator=(const forward_list& x); - forward_list& operator=(forward_list&& x); + forward_list& operator=(forward_list&& x) + noexcept( + allocator_type::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<allocator_type>::value); forward_list& operator=(initializer_list<value_type> il); template <class InputIterator> @@ -100,7 +105,9 @@ iterator erase_after(const_iterator p); iterator erase_after(const_iterator first, const_iterator last); - void swap(forward_list& x); + void swap(forward_list& x) + noexcept(!allocator_type::propagate_on_container_swap::value || + __is_nothrow_swappable<allocator_type>::value); void resize(size_type n); void resize(size_type n, const value_type& v); @@ -152,7 +159,8 @@ const forward_list<T, Allocator>& y); template <class T, class Allocator> - void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y); + void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) + noexcept(x.swap(y)); } // std @@ -370,7 +378,8 @@ static_cast<const __node&>(__before_begin_.first()));} _LIBCPP_INLINE_VISIBILITY - __node_allocator& __alloc() {return __before_begin_.second();} + __node_allocator& __alloc() _NOEXCEPT + {return __before_begin_.second();} _LIBCPP_INLINE_VISIBILITY const __node_allocator& __alloc() const _NOEXCEPT {return __before_begin_.second();} @@ -380,23 +389,27 @@ _LIBCPP_INLINE_VISIBILITY __forward_list_base() + _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) : __before_begin_(__begin_node()) {} _LIBCPP_INLINE_VISIBILITY __forward_list_base(const allocator_type& __a) : __before_begin_(__begin_node(), __node_allocator(__a)) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - __forward_list_base(__forward_list_base&& __x); +public: + __forward_list_base(__forward_list_base&& __x) + _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); __forward_list_base(__forward_list_base&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES private: __forward_list_base(const __forward_list_base&); __forward_list_base& operator=(const __forward_list_base&); -protected: +public: ~__forward_list_base(); +protected: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __forward_list_base& __x) {__copy_assign_alloc(__x, integral_constant<bool, @@ -404,10 +417,16 @@ _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || + is_nothrow_move_assignable<__node_allocator>::value) {__move_assign_alloc(__x, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());} - void swap(__forward_list_base& __x); +public: + void swap(__forward_list_base& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value); +protected: void clear() _NOEXCEPT; private: @@ -422,22 +441,28 @@ } _LIBCPP_INLINE_VISIBILITY - void __move_assign_alloc(__forward_list_base& __x, false_type) {} + void __move_assign_alloc(__forward_list_base& __x, false_type) _NOEXCEPT + {} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__alloc() = _STD::move(__x.__alloc());} _LIBCPP_INLINE_VISIBILITY static void __swap_alloc(__node_allocator& __x, __node_allocator& __y) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) {__swap_alloc(__x, __y, integral_constant<bool, __node_traits::propagate_on_container_swap::value>());} _LIBCPP_INLINE_VISIBILITY static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type) + _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type) + _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value) { using _STD::swap; swap(__x, __y); @@ -449,6 +474,7 @@ template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x) + _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value) : __before_begin_(_STD::move(__x.__before_begin_)) { __x.__before_begin()->__next_ = nullptr; @@ -479,6 +505,8 @@ inline _LIBCPP_INLINE_VISIBILITY void __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) { __swap_alloc(__alloc(), __x.__alloc()); using _STD::swap; @@ -505,6 +533,11 @@ : private __forward_list_base<_Tp, _Alloc> { typedef __forward_list_base<_Tp, _Alloc> base; + typedef typename base::__node_allocator __node_allocator; + typedef typename base::__node __node; + typedef typename base::__node_traits __node_traits; + typedef typename base::__node_pointer __node_pointer; + public: typedef _Tp value_type; typedef _Alloc allocator_type; @@ -519,7 +552,10 @@ typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; - _LIBCPP_INLINE_VISIBILITY forward_list() {} // = default; + _LIBCPP_INLINE_VISIBILITY + forward_list() + _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) + {} // = default; explicit forward_list(const allocator_type& __a); explicit forward_list(size_type __n); forward_list(size_type __n, const value_type& __v); @@ -539,7 +575,9 @@ forward_list(const forward_list& __x, const allocator_type& __a); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY - forward_list(forward_list&& __x) : base(_STD::move(__x)) {} + forward_list(forward_list&& __x) + _NOEXCEPT_(is_nothrow_move_constructible<base>::value) + : base(_STD::move(__x)) {} forward_list(forward_list&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES forward_list(initializer_list<value_type> __il); @@ -549,7 +587,10 @@ forward_list& operator=(const forward_list& __x); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - forward_list& operator=(forward_list&& __x); + forward_list& operator=(forward_list&& __x) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<allocator_type>::value); #endif forward_list& operator=(initializer_list<value_type> __il); @@ -643,7 +684,10 @@ iterator erase_after(const_iterator __f, const_iterator __l); _LIBCPP_INLINE_VISIBILITY - void swap(forward_list& __x) {base::swap(__x);} + void swap(forward_list& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) + {base::swap(__x);} void resize(size_type __n); void resize(size_type __n, const value_type& __v); @@ -685,13 +729,10 @@ void reverse() _NOEXCEPT; private: - typedef typename base::__node_allocator __node_allocator; - typedef typename base::__node __node; - typedef typename base::__node_traits __node_traits; - typedef typename base::__node_pointer __node_pointer; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - void __move_assign(forward_list& __x, true_type); + void __move_assign(forward_list& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); void __move_assign(forward_list& __x, false_type); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -833,6 +874,7 @@ template <class _Tp, class _Alloc> void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { clear(); base::__move_assign_alloc(__x); @@ -857,6 +899,9 @@ inline _LIBCPP_INLINE_VISIBILITY forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(forward_list&& __x) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<allocator_type>::value) { __move_assign(__x, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>()); @@ -1557,6 +1602,7 @@ inline _LIBCPP_INLINE_VISIBILITY void swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } diff --git a/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp b/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp index 491e906..15e082e 100644 --- a/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp +++ b/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp
@@ -17,6 +17,8 @@ #include "../../../MoveOnly.h" #include "../../../test_allocator.h" +#if __has_feature(cxx_noexcept) + template <class T> struct some_alloc { @@ -25,6 +27,8 @@ ~some_alloc() noexcept(false); }; +#endif + int main() { #if __has_feature(cxx_noexcept) diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp new file mode 100644 index 0000000..2236048 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp
@@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// forward_list() +// noexcept(is_nothrow_default_constructible<allocator_type>::value); + +// This tests a conforming extension + +#include <forward_list> +#include <cassert> + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template <class T> +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list<MoveOnly> C; + static_assert(std::is_nothrow_default_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, test_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_default_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, other_allocator<MoveOnly>> C; + static_assert(!std::is_nothrow_default_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; + static_assert(!std::is_nothrow_default_constructible<C>::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp new file mode 100644 index 0000000..9f12ced --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp
@@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// ~forward_list() // implied noexcept; + +#include <forward_list> +#include <cassert> + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +#if __has_feature(cxx_noexcept) + +template <class T> +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); + ~some_alloc() noexcept(false); +}; + +#endif + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list<MoveOnly> C; + static_assert(std::is_nothrow_destructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, test_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_destructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, other_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_destructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; + static_assert(!std::is_nothrow_destructible<C>::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp new file mode 100644 index 0000000..b19e6dc --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp
@@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// forward_list& operator=(forward_list&& c) +// noexcept( +// allocator_type::propagate_on_container_move_assignment::value && +// is_nothrow_move_assignable<allocator_type>::value); + +// This tests a conforming extension + +#include <forward_list> +#include <cassert> + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template <class T> +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list<MoveOnly> C; + static_assert(std::is_nothrow_move_assignable<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, test_allocator<MoveOnly>> C; + static_assert(!std::is_nothrow_move_assignable<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, other_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_move_assignable<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; + static_assert(!std::is_nothrow_move_assignable<C>::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp new file mode 100644 index 0000000..d3a3d52 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp
@@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// forward_list(forward_list&&) +// noexcept(is_nothrow_move_constructible<allocator_type>::value); + +// This tests a conforming extension + +#include <forward_list> +#include <cassert> + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template <class T> +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list<MoveOnly> C; + static_assert(std::is_nothrow_move_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, test_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_move_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, other_allocator<MoveOnly>> C; + static_assert(std::is_nothrow_move_constructible<C>::value, ""); + } + { + typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; + static_assert(!std::is_nothrow_move_constructible<C>::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp new file mode 100644 index 0000000..777a666 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp
@@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// void swap(forward_list& c) +// noexcept(!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable<allocator_type>::value); + +// This tests a conforming extension + +#include <forward_list> +#include <cassert> + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template <class T> +struct some_alloc +{ + typedef T value_type; + + some_alloc() {} + some_alloc(const some_alloc&); + void deallocate(void*, unsigned) {} + + typedef std::true_type propagate_on_container_swap; +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list<MoveOnly> C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list<MoveOnly, test_allocator<MoveOnly>> C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list<MoveOnly, other_allocator<MoveOnly>> C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } +#endif +}